1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 import java.awt.BorderLayout;
36 import java.awt.Font;
37 import java.awt.event.ActionEvent;
38 import java.awt.event.ActionListener;
39 import java.awt.event.ItemEvent;
40 import java.awt.event.ItemListener;
41
42 import javax.swing.*;
43
44 import java.util.*;
45 import java.util.regex.*;
46
47
48
49
50
51
52
53
54
55
56 public final class RangeMenu extends JComboBox implements ActionListener {
57
58 private static final int[][] UNICODE_RANGES = getUnicodeRanges();
59 private static final String[] UNICODE_RANGE_NAMES = getUnicodeRangeNames();
60
61 private boolean useCustomRange = false;
62 private int[] customRange = { 0x0000, 0x007f };
63
64
65 private final JDialog customRangeDialog;
66 private final JTextField customRangeStart = new JTextField( "0000", 4 );
67 private final JTextField customRangeEnd = new JTextField( "007F", 4 );
68 private final int CUSTOM_RANGE_INDEX = UNICODE_RANGE_NAMES.length - 1;
69
70
71 private final Font2DTest parent;
72
73 public static final int SURROGATES_AREA_INDEX = 91;
74
75 public RangeMenu( Font2DTest demo, JFrame f ) {
76 super();
77 parent = demo;
78
79 for ( int i = 0; i < UNICODE_RANGE_NAMES.length; i++ )
80 addItem( UNICODE_RANGE_NAMES[i] );
81
82 setSelectedIndex( 0 );
83 addActionListener( this );
84
85
86 customRangeDialog = new JDialog( f, "Custom Unicode Range", true );
87 customRangeDialog.setResizable( false );
88
89 JPanel dialogTop = new JPanel();
90 JPanel dialogBottom = new JPanel();
91 JButton okButton = new JButton("OK");
92 JLabel from = new JLabel( "From:" );
93 JLabel to = new JLabel("To:");
94 Font labelFont = new Font( "dialog", Font.BOLD, 12 );
95 from.setFont( labelFont );
96 to.setFont( labelFont );
97 okButton.setFont( labelFont );
98
99 dialogTop.add( from );
100 dialogTop.add( customRangeStart );
101 dialogTop.add( to );
102 dialogTop.add( customRangeEnd );
103 dialogBottom.add( okButton );
104 okButton.addActionListener( this );
105
106 customRangeDialog.getContentPane().setLayout( new BorderLayout() );
107 customRangeDialog.getContentPane().add( "North", dialogTop );
108 customRangeDialog.getContentPane().add( "South", dialogBottom );
109 customRangeDialog.pack();
110 }
111
112
113
114 public int[] getSelectedRange() {
115 if ( useCustomRange ) {
116 int startIndex, endIndex;
117 String startText, endText;
118 String empty = "";
119 try {
120 startText = customRangeStart.getText().trim();
121 endText = customRangeEnd.getText().trim();
122 if ( startText.equals(empty) && !endText.equals(empty) ) {
123 endIndex = Integer.parseInt( endText, 16 );
124 startIndex = endIndex - 7*25;
125 }
126 else if ( !startText.equals(empty) && endText.equals(empty) ) {
127 startIndex = Integer.parseInt( startText, 16 );
128 endIndex = startIndex + 7*25;
129 }
130 else {
131 startIndex = Integer.parseInt( customRangeStart.getText(), 16 );
132 endIndex = Integer.parseInt( customRangeEnd.getText(), 16 );
133 }
134 }
135 catch ( Exception e ) {
136
137
138 customRangeStart.setText( Integer.toString( customRange[0], 16 ));
139 customRangeEnd.setText( Integer.toString( customRange[1], 16 ));
140 return customRange;
141 }
142
143 if ( startIndex < 0 )
144 startIndex = 0;
145 if ( endIndex > 0xffff )
146 endIndex = 0xffff;
147 if ( startIndex > endIndex )
148 startIndex = endIndex;
149
150 customRange[0] = startIndex;
151 customRange[1] = endIndex;
152 return customRange;
153 }
154 else
155 return UNICODE_RANGES[ getSelectedIndex() ];
156 }
157
158
159
160 public void setSelectedRange( String name, int start, int end ) {
161 setSelectedItem( name );
162 customRange[0] = start;
163 customRange[1] = end;
164 parent.fireRangeChanged();
165 }
166
167
168
169
170
171 public void actionPerformed( ActionEvent e ) {
172 Object source = e.getSource();
173
174 if ( source instanceof JComboBox ) {
175 String rangeName = (String)((JComboBox)source).getSelectedItem();
176
177 if ( rangeName.equals("Custom...") ) {
178 useCustomRange = true;
179 customRangeDialog.setLocationRelativeTo(parent);
180 customRangeDialog.show();
181 }
182 else {
183 useCustomRange = false;
184 }
185 parent.fireRangeChanged();
186 }
187 else if ( source instanceof JButton ) {
188
189 customRangeDialog.hide();
190 }
191 }
192
193 private static int[][] getUnicodeRanges() {
194 List<Integer> ranges = new ArrayList<>();
195 ranges.add(0);
196 Character.UnicodeBlock currentBlock = Character.UnicodeBlock.of(0);
197 for (int cp = 0x000001; cp < 0x110000; cp++ ) {
198 Character.UnicodeBlock ub = Character.UnicodeBlock.of(cp);
199 if (currentBlock == null) {
200 if (ub != null) {
201 ranges.add(cp);
202 currentBlock = ub;
203 }
204 } else {
205 if (ub == null) {
206 ranges.add(cp - 1);
207 currentBlock = null;
208 } else if (cp == 0x10ffff) {
209 ranges.add(cp);
210 } else if (! ub.equals(currentBlock)) {
211 ranges.add(cp - 1);
212 ranges.add(cp);
213 currentBlock = ub;
214 }
215 }
216 }
217 ranges.add(0x00);
218 ranges.add(0x7f);
219
220 int[][] returnval = new int[ranges.size() / 2][2];
221 for (int i = 0 ; i < ranges.size() / 2 ; i++ ) {
222 returnval[i][0] = ranges.get(2*i);
223 returnval[i][1] = ranges.get(2*i + 1);
224 }
225 return returnval;
226 }
227
228 private static String[] getUnicodeRangeNames() {
229 String[] names = new String[UNICODE_RANGES.length];
230 for (int i = 0 ; i < names.length ; i++ ) {
231 names[i] = titleCase(
232 Character.UnicodeBlock.of(UNICODE_RANGES[i][0]).toString());
233 }
234 names[names.length - 1] = "Custom...";
235 return names;
236 }
237
238 private static String titleCase(String str) {
239 str = str.replaceAll("_", " ");
240 Pattern p = Pattern.compile("(^|\\W)([a-z])");
241 Matcher m = p.matcher(str.toLowerCase(Locale.ROOT));
242 StringBuffer sb = new StringBuffer();
243 while (m.find()) {
244 m.appendReplacement(sb, m.group(1) + m.group(2).toUpperCase(Locale.ROOT));
245 }
246 m.appendTail(sb);
247 return sb.toString().replace("Cjk", "CJK").replace("Nko", "NKo");
248 }
249 }